home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
cmds
/
nfsmount
/
nfsName.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-20
|
34KB
|
1,084 lines
/*
* nfsName.c --
*
* Procedures that interface to a remote NFS filesystem. The procedures
* here are called via the Pfs/Pdev library in response to naming requests
* from the Sprite kernel about files in an NFS filesystem.
*
* Copyright 1988 Regents of the University of California
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*/
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/cmds/nfsmount/RCS/nfsName.c,v 1.18 91/09/24 11:47:50 mottsmth Exp $ SPRITE (Berkeley)";
#endif not lint
#include "stdio.h"
#include "nfs.h"
#include "sys/stat.h"
int nfsToSpriteFileType[] = {
FS_PSEUDO_DEV, /* NFNON */
FS_FILE, /* NFREG */
FS_DIRECTORY, /* NFDIR */
FS_DEVICE, /* NFBLK */
FS_DEVICE, /* NFCHR */
FS_SYMBOLIC_LINK, /* NFLNK */
};
int spriteToNfsModeType[] = {
S_IFREG, /* FS_FILE */
S_IFDIR, /* FS_DIRECTORY */
S_IFLNK, /* FS_SYMBOLIC_LINK */
S_IFLNK, /* FS_REMOTE_LINK */
S_IFCHR, /* FS_DEVICE */
0, /* FS_REMOTE_DEVICE - not used by Sprite */
0, /* FS_LOCAL_PIPE - never seen by open */
S_IFIFO, /* FS_NAMED_PIPE */
S_IFSOCK, /* FS_PSEUDO_DEVICE */
S_IFLNK, /* FS_PSEUDO_FS */
0, /* FS_XTRA_FILE - used to test new Sprite types */
};
/*
* Open file table. A simple array of pointers to nfs_fh that
* is used to map between a Fs_FileID we give the Sprite kernel
* each time an NFS file is opened. The minor field of the Sprite
* fileID is used as an index into this array of pointers to NFS handles.
*/
NfsOpenFile **nfsFileTable = (NfsOpenFile **)NULL;
NfsOpenFile **nextFreeSlot = (NfsOpenFile **)NULL;
int nfsFileTableSize = 0;
/*
* The following macro is used to map from a Sprite file ID to an NFS handle.
* This is used to interpret the prefixID passed to us on lookup operations.
* The Sprite kernel passes us a completly zero'd fileID for
* names that start at our root. Otherwise it passes us the
* fileID we gave it when the process opened its current directory.
*/
#define PrefixIDToHandle(prefixID) \
( (prefixID.type == TYPE_ROOT) ? (NfsOpenFile *)NULL : \
((nfsFileTable == (NfsOpenFile **)NULL) ? (NfsOpenFile *)NULL : \
nfsFileTable[prefixID.minor] ) )
/*
* The set of callback procedures given to Pfs_Open. These define the
* procedures called in response to pseudo-filesystem naming operations.
*/
Pfs_CallBacks nfsNameService= {
NfsOpen, /* PFS_OPEN */
NfsGetAttrPath, /* PFS_GET_ATTR */
NfsSetAttrPath, /* PFS_SET_ATTR */
NfsMakeDevice, /* PFS_MAKE_DEVICE */
NfsMakeDir, /* PFS_MAKE_DIR */
NfsRemove, /* PFS_REMOVE */
NfsRemoveDir, /* PFS_REMOVE_DIR */
NfsRename, /* PFS_RENAME */
NfsHardLink, /* PFS_HARD_LINK */
NfsSymLink, /* PFS_SYM_LINK */
NfsDomainInfo, /* PFS_DOMAIN_INFO */
};
void NfsSetupAuth();
/*
*----------------------------------------------------------------------
*
* Nfs_InitClient --
*
* Set up the CLIENT data structure needed to do SUN RPC to the
* NFS server running on a particular host.
*
* Results:
* None.
*
* Side effects:
* Calls clnt_create which sets up sockets and other related state.
*
*----------------------------------------------------------------------
*/
CLIENT *
Nfs_InitClient(host)
char *host;
{
register CLIENT *clnt;
VoidPtr voidArg;
VoidPtr voidRes;
int retryCnt = -1; /* infinite retries */
clnt = clnt_create(host, NFS_PROGRAM, NFS_VERSION, "udp");
if (clnt == (CLIENT *)NULL) {
clnt_pcreateerror(host);
} else {
clnt->cl_auth = authunix_create_default();
if (!clnt_control(clnt, CLSET_RETRY_COUNT, &retryCnt)) {
clnt_perror(clnt, "clnt_control");
} else {
voidRes = nfsproc_null_2(&voidArg, clnt);
if (voidRes == (VoidPtr)NULL) {
clnt_perror(clnt, "nfsproc_null_2");
} else if (pdev_Trace) {
printf("Null RPC to NFS service at %s succeeded\n", host);
}
}
}
return(clnt);
}
/*
*----------------------------------------------------------------------
*
* NfsProbe --
*
* Called to test NFS access. This dos a stat of the root of the
* NFS system we have mounted. The stat information is returned
* so the pseudo-file-system server can properly establish the
* user-visible fileID of the root.
*
* Results:
* 1 if probe succeeded, 0 otherwise.
*
* Side effects:
* Fills in the NFS attributes of the root directory.
*
*----------------------------------------------------------------------
*/
int
NfsProbe(nfsPtr, print, nfsAttrPtr)
NfsState *nfsPtr; /* Top level state for NFS connection */
int print; /* 1 to print out attributes */
attrstat *nfsAttrPtr; /* NFS attributes of root */
{
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_GETATTR, xdr_nfs_fh,
nfsPtr->mountHandle,
xdr_attrstat, nfsAttrPtr, nfsTimeout) != RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_GETATTR");
return(0);
} else if (nfsAttrPtr->status != NFS_OK) {
printf("NfsProbe: Get attributes status %d\n", nfsAttrPtr->status);
return(0);
} else if (print) {
printf("Attributes of %s:%s\n", nfsPtr->host, nfsPtr->nfsName);
printf("\tFileID %x FS_ID %x\n",
nfsAttrPtr->attrstat_u.attributes.fileid,
nfsAttrPtr->attrstat_u.attributes.fsid);
printf("\tType %d mode 0%o links %d size %d\n",
nfsAttrPtr->attrstat_u.attributes.type,
nfsAttrPtr->attrstat_u.attributes.mode,
nfsAttrPtr->attrstat_u.attributes.nlink,
nfsAttrPtr->attrstat_u.attributes.size);
}
return(1);
}
/*
*----------------------------------------------------------------------
*
* NfsOpen --
*
* Called to open a file in the NFS system. This does the open
* with the NFS server and then opens a new pseudo-device connection
* that will be used for all further operatiosn on the NFS file.
*
* Results:
* None.
*
* Side effects:
* Calls clnt_create which sets up sockets and other related state.
*
*----------------------------------------------------------------------
*/
int
NfsOpen(clientData, name, openArgsPtr, redirectInfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *name; /* Pathname to open */
register Fs_OpenArgs *openArgsPtr; /* Bundled arguments */
Fs_RedirectInfo *redirectInfoPtr; /* Used when name leaves our domain */
{
NfsState *nfsPtr = (NfsState *)clientData;
NfsOpenFile *cwdFilePtr;
Pdev_Stream *streamPtr;
diropres longDirResults;
diropokres *dirResultsPtr = &longDirResults.diropres_u.diropres;
createargs createArgs;
diropargs *wherePtr = &createArgs.where;
int status;
char component[NFS_MAXNAMLEN];
int created = 0;
int writeBehind = nfs_PdevWriteBehind;
wherePtr->name = component;
cwdFilePtr = PrefixIDToHandle(openArgsPtr->prefixID);
NfsSetupAuth(nfsPtr, cwdFilePtr, &openArgsPtr->id);
status = NfsLookup(nfsPtr, cwdFilePtr, name, openArgsPtr->useFlags,
dirResultsPtr, &wherePtr, redirectInfoPtr);
if (status == NFSERR_NOENT && wherePtr != (diropargs *)NULL &&
(openArgsPtr->useFlags & FS_CREATE)) {
/*
* We need to create the file. NfsLookup has set up createArgs.where
* to have the handle on the parent and the component to create.
*/
register sattr *sattrPtr = &createArgs.attributes;
sattrPtr->mode = openArgsPtr->permissions & 07777;
if (openArgsPtr->type >= 0 && openArgsPtr->type <= FS_XTRA_FILE) {
sattrPtr->mode |= spriteToNfsModeType[openArgsPtr->type];
} else {
printf("Open(\"%s\") bad type %d\n", name, openArgsPtr->type);
return(GEN_INVALID_ARG);
}
sattrPtr->uid = openArgsPtr->id.user;
sattrPtr->gid = -1;
sattrPtr->size = 0;
sattrPtr->atime.seconds = -1;
sattrPtr->atime.useconds = -1;
sattrPtr->mtime.seconds = -1;
sattrPtr->mtime.useconds = -1;
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_CREATE, xdr_createargs,
&createArgs, xdr_diropres, &longDirResults, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_CREATE");
return(FAILURE);
}
status = longDirResults.status;
created = 1;
}
if (status != NFS_OK) {
status = NfsStatusMap(status);
} else {
register Fs_FileID *fileIDPtr;
register int full = 0;
/*
* We've got a good handle on the NFS file. Time to do our own
* permission checking cause the NFS server is pretty lame.
*/
status = CheckPermissions(&dirResultsPtr->attributes, created,
openArgsPtr->useFlags, &openArgsPtr->id, openArgsPtr->type);
if (status != SUCCESS) {
return(status);
}
/*
* Save our file handle in an array indexed by part of the Fs_FileID
* we'll give to the Sprite kernel and to the pdev callback library.
* This will let us get back to the handle from prefixID's in open
* arguments, and from the client data passed to us from the callback
* library.
*/
if (nfsFileTable == (NfsOpenFile **)NULL) {
/*
* Allocate and initialize the table. It might grow later.
*/
nfsFileTable = (NfsOpenFile **)malloc(64 * sizeof(NfsOpenFile *));
bzero((char *)nfsFileTable, 64 * sizeof(NfsOpenFile *));
nextFreeSlot = &nfsFileTable[0];
nfsFileTableSize = 64;
}
while (*nextFreeSlot != (NfsOpenFile *)NULL) {
nextFreeSlot++;
if (nextFreeSlot >= &nfsFileTable[nfsFileTableSize]) {
if (!full){
nextFreeSlot = &nfsFileTable[0];
full = 1;
} else {
/*
* Grow the table.
*/
register NfsOpenFile **newTable =
(NfsOpenFile **)malloc(nfsFileTableSize * 2 *
sizeof(NfsOpenFile *));
bcopy((char *)nfsFileTable, (char *)newTable,
nfsFileTableSize * sizeof(NfsOpenFile *));
bzero((char *)&newTable[nfsFileTableSize],
nfsFileTableSize * sizeof(NfsOpenFile *));
free((char *)nfsFileTable);
nfsFileTable = newTable;
nextFreeSlot = &nfsFileTable[nfsFileTableSize];
nfsFileTableSize *= 2;
}
}
}
/*
* Save the NFS handle and the UNIX authentication of this user.
*/
*nextFreeSlot = (NfsOpenFile *)malloc(sizeof(NfsOpenFile));
(*nextFreeSlot)->handlePtr = (nfs_fh *)malloc(sizeof(nfs_fh));
bcopy((char *)&dirResultsPtr->file,
(char *)(*nextFreeSlot)->handlePtr, NFS_FHSIZE);
{
register int numGroups;
numGroups = (openArgsPtr->id.numGroupIDs <= NGRPS) ?
openArgsPtr->id.numGroupIDs : NGRPS ;
(*nextFreeSlot)->authPtr = authunix_create(myhostname,
openArgsPtr->id.user, openArgsPtr->id.group[0],
numGroups, openArgsPtr->id.group);
}
(*nextFreeSlot)->openFlags = openArgsPtr->useFlags;
/*
* Tell the Sprite kernel to set up a pseudo-device connection
* over which we'll see all future operations on the NFS file.
* The fileID we give here will come back to us if this open is
* for a chdir(); the fileID will be passed as the prefixID in
* the openArgs. We set the type in order to differentiate
* it from the type of zero used for the fileID of our root.
*/
fileIDPtr = (Fs_FileID *)malloc(sizeof(Fs_FileID));
fileIDPtr->minor = nextFreeSlot - nfsFileTable;
fileIDPtr->major = 0;
fileIDPtr->serverID = (int)nfsPtr;
switch(dirResultsPtr->attributes.type) {
case NFDIR:
fileIDPtr->type = TYPE_DIRECTORY;
break;
case NFLNK:
fileIDPtr->type = TYPE_SYMLINK;
break;
default:
fileIDPtr->type = TYPE_FILE;
writeBehind = 1;
break;
}
streamPtr = Pfs_OpenConnection(nfsPtr->pfsToken, fileIDPtr,
(16 * 1024) + 128, /* request buffer size */
0, NULL, /* no read buffer */
FS_READABLE | FS_WRITABLE, &nfsFileService);
/*
* Enable write-behind. We'd like to let a writer overlap its writes.
* The request buffer is large enough for 2 8K block writes. Using
* write-behind increases the write bandwidth from 9k/sec to 40k/sec.
*/
if (streamPtr != (Pdev_Stream *)NULL) {
if (Fs_IOControl(streamPtr->streamID, IOC_PDEV_WRITE_BEHIND,
sizeof(int), &writeBehind, 0, NULL) != 0) {
fprintf(stderr, "IOC_PDEV_WRITE_BEHIND failed\n");
}
streamPtr->clientData = (ClientData)fileIDPtr;
} else {
status = EINVAL;
}
}
return(status);
}
/*
*----------------------------------------------------------------------
*
* NfsSetupAuth --
*
* This procedure initializes the authentication information for
* the NFS client structure. It uses the AUTH * of the open
* NFS file if possible. For absolute pathnames, however, this
* hasn't been setup yet so we do it here.
*
* Results:
* None.
*
* Side effects:
* For absolute paths we create an AUTH structure that won't get free'd.
*
* True; it wasn't being freed, and at 500 bytes a pop it was
* consuming major heap space. I added oldAuth to remember the pointer
* and free it next time we come through here. JMS.
*
*----------------------------------------------------------------------
*/
void
NfsSetupAuth(nfsPtr, cwdFilePtr, idPtr)
NfsState *nfsPtr;
NfsOpenFile *cwdFilePtr;
Fs_UserIDs *idPtr;
{
static AUTH *oldAuth = (AUTH *)NULL;
if (oldAuth != (AUTH *)NULL) {
AUTH_DESTROY(oldAuth);
oldAuth = (AUTH *)NULL;
}
if (cwdFilePtr != (NfsOpenFile *)NULL) {
nfsPtr->nfsClnt->cl_auth = cwdFilePtr->authPtr;
} else {
if (idPtr->numGroupIDs > NGRPS) {
/*
* Patch so xdr_auth_unix doesn't fail.
*/
idPtr->numGroupIDs = NGRPS;
}
oldAuth = nfsPtr->nfsClnt->cl_auth = authunix_create(myhostname,
idPtr->user, idPtr->group[0], idPtr->numGroupIDs, idPtr->group);
}
}
/*
*----------------------------------------------------------------------
*
* CheckPermissions --
*
* Client side permission checking so we can make an open fail
* if the permissions are not sufficient. The NFS server lets
* any lookup request succeed if the client has permission over
* the search path, and then does more permission checking at
* each I/O. Accordingly, we have to do a little more work at open time.
*
* Results:
* SUCCESS or an error code.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
CheckPermissions(nfsAttrPtr, created, useFlags, idPtr, wantType)
register fattr *nfsAttrPtr;
int created;
register int useFlags;
register Fs_UserIDs *idPtr;
register int wantType;
{
register int thisType = nfsToSpriteFileType[(int)nfsAttrPtr->type];
register int index;
register int permBits;
register int *groupPtr;
register int status;
/*
* Make sure the file type matches. FS_FILE means any type, otherwise
* it should match exactly. We have to patch 'thisType' of
* SYMBOLIC_LINK to REMOTE_LINK because of a Sprite kernel bug
* where it asks for REMOTE_LINKS instead of symbolic links
* when implementing the readlink() system call.
*/
if (wantType == FS_REMOTE_LINK) {
wantType = FS_SYMBOLIC_LINK;
}
if ((wantType != FS_FILE) && (wantType != thisType)) {
if (wantType == FS_DIRECTORY) {
return(FS_NOT_DIRECTORY);
} else {
return(FS_WRONG_TYPE);
}
}
/*
* Dis-allow execution of directories...
*/
if ((wantType == FS_FILE) && (useFlags & FS_EXECUTE) &&
(thisType != FS_FILE)) {
return(FS_WRONG_TYPE);
}
/* Removed check which disallowed execution of file across NFS */
/* since the kernel can now do it (without setuid or setgid) JMS */
if (idPtr->user == 0) {
/*
* For normal files, only check for execute permission. This
* prevents root from being able to execute ordinary files by
* accident. However, root has complete access to directories.
*/
if (thisType == FS_DIRECTORY) {
return(SUCCESS);
}
useFlags &= FS_EXECUTE;
}
/*
* Check read/write/exec permissions against one of the owner bits,
* the group bits, or the world bits. 'permBits' is set to
* be the corresponding bits from the attributes and then
* shifted over so the comparisions are against the WORLD bits.
*/
if (idPtr->user == nfsAttrPtr->uid) {
/*
* Because NFS is stateless it can't do permission checking right.
* A direct quote:
* "the server's permission checking algorithm should allow the owner
* of a file to access it regardless of the permission setting"
*
* Thus we don't enforce any permission checking on the owner here
* if the file has just been created.
* This lets programs like "update" and "cp -p" that preserve
* permissions copy a read-only file.
*/
if (!created) {
permBits = (nfsAttrPtr->mode >> 6) & 07;
} else {
permBits = 07;
}
} else {
for (index = idPtr->numGroupIDs, groupPtr = idPtr->group;
index > 0;
index--, groupPtr++) {
if (*groupPtr == nfsAttrPtr->gid) {
permBits = (nfsAttrPtr->mode >> 3) & 07;
goto havePermBits;
}
}
permBits = nfsAttrPtr->mode & 07;
}
havePermBits:
if (((useFlags & FS_READ) && ((permBits & FS_WORLD_READ) == 0)) ||
((useFlags & FS_WRITE) && ((permBits & FS_WORLD_WRITE) == 0)) ||
((useFlags & FS_EXECUTE) && ((permBits & FS_WORLD_EXEC) == 0))) {
/*
* The file's permission don't include what is needed.
*/
status = FS_NO_ACCESS;
} else {
status = SUCCESS;
}
return(status);
}
/*
*----------------------------------------------------------------------
*
* NfsGetAttrPath --
*
* Called to stat a file in the NFS system.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsGetAttrPath(clientData, name, openArgsPtr, spriteAttrPtr, redirectInfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *name; /* Pathname to open */
Fs_OpenArgs *openArgsPtr; /* Bundled arguments */
Fs_Attributes *spriteAttrPtr; /* Return - attributes of the file */
Fs_RedirectInfo *redirectInfoPtr; /* Used when name leaves our domain */
{
NfsState *nfsPtr = (NfsState *)clientData;
diropokres dirResults;
fattr *nfsAttrPtr = &dirResults.attributes;
NfsOpenFile *cwdFilePtr;
int status;
cwdFilePtr = PrefixIDToHandle(openArgsPtr->prefixID);
status = NfsLookup(nfsPtr, cwdFilePtr, name, openArgsPtr->useFlags,
&dirResults, (diropargs *)NULL, redirectInfoPtr);
if (status != NFS_OK) {
return(NfsStatusMap(status));
}
NfsToSpriteAttr(nfsAttrPtr, spriteAttrPtr);
return(0);
}
/*
*----------------------------------------------------------------------
*
* NfsSetAttrPath --
*
* Called to change attributes of a file in the NFS system.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsSetAttrPath(clientData, name, openArgsPtr, flags, attrPtr, redirectInfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *name; /* Pathname to open */
Fs_OpenArgs *openArgsPtr; /* Bundled arguments */
int flags; /* Specify which attributes to set */
Fs_Attributes *attrPtr; /* New attributes of the file */
Fs_RedirectInfo *redirectInfoPtr; /* Used when name leaves our domain */
{
NfsState *nfsPtr = (NfsState *)clientData;
diropokres dirResults;
sattrargs sattrArgs;
attrstat attrStat;
NfsOpenFile *cwdFilePtr;
int status;
cwdFilePtr = PrefixIDToHandle(openArgsPtr->prefixID);
status = NfsLookup(nfsPtr, cwdFilePtr, name, openArgsPtr->useFlags,
&dirResults, (diropargs **)NULL, redirectInfoPtr);
if (status != NFS_OK) {
return(NfsStatusMap(status));
}
bcopy((char *)&dirResults.file, (char *)&sattrArgs.file, sizeof(nfs_fh));
SpriteToNfsAttr(flags, attrPtr, &sattrArgs.attributes);
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_SETATTR, xdr_sattrargs, &sattrArgs,
xdr_attrstat, &attrStat, nfsTimeout) != RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_SETATTR");
return(FAILURE);
} else {
return(NfsStatusMap((int)attrStat.status));
}
}
/*
*----------------------------------------------------------------------
*
* NfsMakeDevice --
*
* Called to create a special file (device) in the NFS system.
* This isn't supported by the NFS protocol.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsMakeDevice(clientData, name, makeDevArgsPtr, redirectInfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *name; /* Pathname to open */
Fs_MakeDeviceArgs *makeDevArgsPtr; /* Bundled arguments */
Fs_RedirectInfo *redirectInfoPtr; /* Used when name leaves our domain */
{
return(FS_NO_ACCESS);
}
/*
*----------------------------------------------------------------------
*
* NfsMakeDir --
*
* Called to make a directory in the NFS system.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsMakeDir(clientData, name, openArgsPtr, redirectInfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *name; /* Pathname to open */
Fs_OpenArgs *openArgsPtr; /* Bundled arguments */
Fs_RedirectInfo *redirectInfoPtr; /* Used when name leaves our domain */
{
NfsOpenFile *cwdFilePtr;
NfsState *nfsPtr = (NfsState *)clientData;
diropres longDirResults;
diropokres *dirResultsPtr = &longDirResults.diropres_u.diropres;
createargs createArgs;
diropargs *wherePtr = &createArgs.where;
register sattr *sattrPtr = &createArgs.attributes;
int status;
char component[NFS_MAXNAMLEN];
wherePtr->name = component;
cwdFilePtr = PrefixIDToHandle(openArgsPtr->prefixID);
status = NfsLookup(nfsPtr, cwdFilePtr, name, openArgsPtr->useFlags,
dirResultsPtr, &wherePtr, redirectInfoPtr);
if (status == NFS_OK) {
return(EEXIST);
} else if (status == NFSERR_NOENT) {
sattrPtr->mode = openArgsPtr->permissions & 07777 | S_IFDIR;
sattrPtr->uid = openArgsPtr->id.user;
sattrPtr->gid = -1;
sattrPtr->size = 0;
sattrPtr->atime.seconds = -1;
sattrPtr->atime.useconds = -1;
sattrPtr->mtime.seconds = -1;
sattrPtr->mtime.useconds = -1;
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_MKDIR, xdr_createargs,
&createArgs, xdr_diropres, &longDirResults, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_MKDIR");
return(FAILURE);
}
status = longDirResults.status;
}
return(NfsStatusMap(status));
}
/*
*----------------------------------------------------------------------
*
* NfsRemove --
*
* Called to remove a file from the NFS system.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsRemove(clientData, name, lookupArgsPtr, redirectInfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *name; /* Pathname to open */
Fs_LookupArgs *lookupArgsPtr; /* Bundled arguments */
Fs_RedirectInfo *redirectInfoPtr; /* Used when name leaves our domain */
{
NfsOpenFile *cwdFilePtr;
NfsState *nfsPtr = (NfsState *)clientData;
diropokres dirResults;
diropargs dirOpArgs;
diropargs *wherePtr = &dirOpArgs;
nfsstat nfsStatus;
int status;
char component[NFS_MAXNAMLEN];
wherePtr->name = component;
cwdFilePtr = PrefixIDToHandle(lookupArgsPtr->prefixID);
status = NfsLookup(nfsPtr, cwdFilePtr, name, lookupArgsPtr->useFlags,
&dirResults, &wherePtr, redirectInfoPtr);
if (status == NFS_OK) {
if (dirResults.attributes.type == NFDIR) {
return(FS_WRONG_TYPE);
}
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_REMOVE, xdr_diropargs,
wherePtr, xdr_nfsstat, &nfsStatus, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_REMOVE");
return(FAILURE);
}
status = (int)nfsStatus;
}
return(NfsStatusMap(status));
}
/*
*----------------------------------------------------------------------
*
* NfsRemoveDir --
*
* Called to remove a directory from the NFS system.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsRemoveDir(clientData, name, lookupArgsPtr, redirectInfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *name; /* Pathname to open */
Fs_LookupArgs *lookupArgsPtr; /* Bundled arguments */
Fs_RedirectInfo *redirectInfoPtr; /* Used when name leaves our domain */
{
NfsOpenFile *cwdFilePtr;
NfsState *nfsPtr = (NfsState *)clientData;
diropokres dirResults;
diropargs dirOpArgs;
diropargs *wherePtr = &dirOpArgs;
nfsstat nfsStatus;
int status;
char component[NFS_MAXNAMLEN];
wherePtr->name = component;
cwdFilePtr = PrefixIDToHandle(lookupArgsPtr->prefixID);
status = NfsLookup(nfsPtr, cwdFilePtr, name, lookupArgsPtr->useFlags,
&dirResults, &wherePtr, redirectInfoPtr);
if (status == NFS_OK) {
if (dirResults.attributes.type != NFDIR) {
return(FS_NOT_DIRECTORY);
}
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_RMDIR, xdr_diropargs,
wherePtr, xdr_nfsstat, &nfsStatus, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_RMDIR");
return(FAILURE);
}
status = (int)nfsStatus;
}
return(NfsStatusMap(status));
}
/*
*----------------------------------------------------------------------
*
* NfsRename --
*
* Called to rename a file in the NFS system.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsRename(clientData, srcName, dstName, twoNameArgsPtr, redirect2InfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *srcName; /* Original name */
char *dstName; /* New name */
Fs_2PathParams *twoNameArgsPtr; /* Lookup args plus prefixID2 */
Fs_2PathRedirectInfo *redirect2InfoPtr;/* Used when name leaves our domain */
{
NfsOpenFile *cwdFilePtr;
NfsState *nfsPtr = (NfsState *)clientData;
diropokres dirResults;
renameargs rename;
diropargs *fromPtr = &rename.from;
diropargs *toPtr = &rename.to;
nfsstat nfsStatus;
int status;
char component[NFS_MAXNAMLEN];
char component2[NFS_MAXNAMLEN];
Fs_RedirectInfo redirectInfo;
fromPtr->name = component;
cwdFilePtr = PrefixIDToHandle(twoNameArgsPtr->lookup.prefixID);
status = NfsLookup(nfsPtr, cwdFilePtr, srcName,
twoNameArgsPtr->lookup.useFlags,
&dirResults, &fromPtr, &redirectInfo);
if (status == EREMOTE) {
redirect2InfoPtr->name1ErrorP = 1;
redirect2InfoPtr->prefixLength = redirectInfo.prefixLength;
strcpy(redirect2InfoPtr->fileName, redirectInfo.fileName);
return(EREMOTE);
} else if (status == NFS_OK) {
if (twoNameArgsPtr->prefixID2.type == -1) {
redirect2InfoPtr->name1ErrorP = 0;
redirect2InfoPtr->prefixLength = 0;
redirect2InfoPtr->fileName[0] = '\0';
return(FS_CROSS_DOMAIN_OPERATION);
}
toPtr->name = component2;
cwdFilePtr = PrefixIDToHandle(twoNameArgsPtr->prefixID2);
status = NfsLookup(nfsPtr, cwdFilePtr, dstName,
twoNameArgsPtr->lookup.useFlags,
&dirResults, &toPtr, &redirectInfo);
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_RENAME, xdr_renameargs,
&rename, xdr_nfsstat, &nfsStatus, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_RENAME");
return(FAILURE);
}
status = (int)nfsStatus;
}
return(NfsStatusMap(status));
}
/*
*----------------------------------------------------------------------
*
* NfsHardLink --
*
* Make a hard link between two files in the NFS system.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsHardLink(clientData, srcName, dstName, twoNameArgsPtr, redirect2InfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *srcName; /* Original name */
char *dstName; /* New name */
Fs_2PathParams *twoNameArgsPtr; /* Lookup args plus prefixID2 */
Fs_2PathRedirectInfo *redirect2InfoPtr;/* Used when name leaves our domain */
{
NfsOpenFile *cwdFilePtr;
NfsState *nfsPtr = (NfsState *)clientData;
diropokres dirResults;
linkargs link;
diropargs *toPtr = &link.to;
nfsstat nfsStatus;
int status;
char component[NFS_MAXNAMLEN];
Fs_RedirectInfo redirectInfo;
cwdFilePtr = PrefixIDToHandle(twoNameArgsPtr->lookup.prefixID);
status = NfsLookup(nfsPtr, cwdFilePtr, srcName,
twoNameArgsPtr->lookup.useFlags,
&dirResults, (diropargs **)NULL, &redirectInfo);
if (status == EREMOTE) {
redirect2InfoPtr->name1ErrorP = 1;
redirect2InfoPtr->prefixLength = redirectInfo.prefixLength;
strcpy(redirect2InfoPtr->fileName, redirectInfo.fileName);
return(EREMOTE);
} else if (status == NFS_OK) {
if (twoNameArgsPtr->prefixID2.type == -1) {
redirect2InfoPtr->name1ErrorP = 0;
redirect2InfoPtr->prefixLength = 0;
redirect2InfoPtr->fileName[0] = '\0';
return(FS_CROSS_DOMAIN_OPERATION);
}
bcopy((char *)&dirResults.file, (char *)&link.from, sizeof(nfs_fh));
toPtr->name = component;
cwdFilePtr = PrefixIDToHandle(twoNameArgsPtr->prefixID2);
status = NfsLookup(nfsPtr, cwdFilePtr, dstName,
twoNameArgsPtr->lookup.useFlags,
&dirResults, &toPtr, &redirectInfo);
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_LINK, xdr_linkargs,
&link, xdr_nfsstat, &nfsStatus, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_LINK");
return(FAILURE);
}
status = (int)nfsStatus;
}
return(NfsStatusMap(status));
}
/*
*----------------------------------------------------------------------
*
* NfsSymLink --
*
* Called to make a symbolic link in the NFS system.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsSymLink(clientData, linkName, value, openArgsPtr, redirectInfoPtr)
ClientData clientData; /* Ref. to NfsState */
char *linkName; /* Original name */
char *value; /* New name */
Fs_OpenArgs *openArgsPtr; /* Open arguments */
Fs_RedirectInfo *redirectInfoPtr; /* Used when name leaves our domain */
{
NfsOpenFile *cwdFilePtr;
NfsState *nfsPtr = (NfsState *)clientData;
diropokres dirResults;
symlinkargs symLinkArgs;
diropargs *wherePtr = &symLinkArgs.from;
register sattr *sattrPtr = &symLinkArgs.attributes;
nfsstat nfsStatus;
int status;
char component[NFS_MAXNAMLEN];
symLinkArgs.to = value;
wherePtr->name = component;
cwdFilePtr = PrefixIDToHandle(openArgsPtr->prefixID);
status = NfsLookup(nfsPtr, cwdFilePtr, linkName,
openArgsPtr->useFlags,
&dirResults, &wherePtr, redirectInfoPtr);
if (status == NFS_OK) {
return(EEXIST);
} else if (status == NFSERR_NOENT) {
sattrPtr->mode = openArgsPtr->permissions & 07777 | S_IFLNK;
sattrPtr->uid = openArgsPtr->id.user;
sattrPtr->gid = -1;
sattrPtr->size = strlen(value);
sattrPtr->atime.seconds = -1;
sattrPtr->atime.useconds = -1;
sattrPtr->mtime.seconds = -1;
sattrPtr->mtime.useconds = -1;
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_SYMLINK, xdr_symlinkargs,
&symLinkArgs, xdr_nfsstat, &nfsStatus, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_MKDIR");
return(FAILURE);
}
status = (int)nfsStatus;
}
return(status);
}
/*
*----------------------------------------------------------------------
*
* NfsDomainInfo --
*
* Called to find out about an NFS file system.
*
* Results:
* The number of blocks and the number of free blocks in the file system.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
/*ARGSUSED*/
int
NfsDomainInfo(clientData, fileIDPtr, domainInfoPtr)
ClientData clientData; /* Ref. to NfsState */
Fs_FileID *fileIDPtr; /* Handle on top-level directory */
Fs_DomainInfo *domainInfoPtr; /* Return information */
{
NfsState *nfsPtr = (NfsState *)clientData;
statfsres fsStat;
if (clnt_call(nfsPtr->nfsClnt, NFSPROC_STATFS, xdr_nfs_fh,
nfsPtr->mountHandle, xdr_statfsres, &fsStat, nfsTimeout)
!= RPC_SUCCESS) {
clnt_perror(nfsPtr->nfsClnt, "NFSPROC_STATFS");
return(FAILURE);
} else if (fsStat.status != NFS_OK) {
return(fsStat.status);
} else {
domainInfoPtr->maxKbytes = fsStat.statfsres_u.reply.blocks *
fsStat.statfsres_u.reply.bsize / 1024;
domainInfoPtr->freeKbytes = fsStat.statfsres_u.reply.bfree *
fsStat.statfsres_u.reply.bsize / 1024;
domainInfoPtr->maxFileDesc = -1;
domainInfoPtr->freeFileDesc = -1;
domainInfoPtr->blockSize = fsStat.statfsres_u.reply.bsize;
domainInfoPtr->optSize = fsStat.statfsres_u.reply.tsize;
return(SUCCESS);
}
}
/*
*----------------------------------------------------------------------
*
* NfsHandlePrint --
*
* Print out an NFS handle.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
NfsHandlePrint(handlePtr)
nfs_fh *handlePtr;
{
register int i;
register int *intPtr = (int *)handlePtr;
printf("<");
for (i=0 ; i<FHSIZE ; i += sizeof(int)) {
printf("%x,", *intPtr);
intPtr++;
}
printf(">");
}